home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 October
/
CHIP Turkiye Ekim 2000.iso
/
prog
/
naps
/
04
/
setup.exe
/
Gnucleus
/
MainFrm.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-07-15
|
24KB
|
907 lines
/********************************************************************************
Gnucleus - A node application for the Gnutella network
Copyright (C) 2000 John Marshall
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For support, questions, comments, etc...
E-Mail:
swabby@c0re.net
Address:
21 Cadogan Way
Nashua, NH, USA 03062
********************************************************************************/
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "Gnucleus.h"
#include "GnucleusDoc.h"
#include "ViewConnect.h"
#include "MainFrm.h"
#include "GnuHash.h"
#include "GnuControl.h"
#define WM_ICON_NOTIFY WM_USER+10
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
ON_COMMAND(ID_OPEN, OnOpenFromTray)
ON_WM_SHOWWINDOW()
ON_WM_NCACTIVATE()
ON_WM_NCLBUTTONUP()
ON_WM_NCLBUTTONDOWN()
ON_WM_NCMOUSEMOVE()
ON_WM_NCPAINT()
ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_RECV,
ID_INDICATOR_SEND
};
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
Doc = (CGnucleusDoc *) ((CGnucleusApp *) AfxGetApp())->MasterDoc;
m_bUseTrayIcon = TRUE;
Strike = 0;
InitializeTrayIcon();
}
CMainFrame::~CMainFrame()
{
RemoveIcon();
m_wndTrayIcon.DestroyWindow();
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndDlgBar.Create(this, IDR_MAINFRAME,
CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
{
TRACE0("Failed to create dialogbar\n");
return -1; // fail to create
}
else
{
CComboBox* cbptr = ((CComboBox *) m_wndDlgBar.GetDlgItem(IDC_COMBO_SPEED));
cbptr->InsertString(0, "T3 (or Greater)");
cbptr->InsertString(0, "T1");
cbptr->InsertString(0, "DSL");
cbptr->InsertString(0, "Cable");
cbptr->InsertString(0, "ISDN-128K");
cbptr->InsertString(0, "ISDN-56K");
cbptr->InsertString(0, "56K Modem");
cbptr->InsertString(0, "33.6 Modem");
cbptr->InsertString(0, "28.8 Modem");
cbptr->InsertString(0, "14.4 Modem");
cbptr->InsertString(0, "");
}
if (!m_wndReBar.Create(this) ||
!m_wndReBar.AddBar(&m_wndToolBar) ||
!m_wndReBar.AddBar(&m_wndDlgBar))
{
TRACE0("Failed to create rebar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
else
{
m_wndStatusBar.SetPaneInfo(1, ID_INDICATOR_RECV, SBPS_NORMAL, 140);
m_wndStatusBar.SetPaneInfo(2, ID_INDICATOR_SEND, SBPS_NORMAL, 125);
}
if (!CreateTrayIcon(this, WM_ICON_NOTIFY, _T("Gnucleus"), AfxGetApp()->LoadIcon(IDR_MAINFRAME),
IDR_TRAY))
{
TRACE0("Failed to create system tray icon.\n");
return -1; // fail to create
}
else
{
HideIcon();
if (m_bOwnerCreated)
{
ShowTaskBarButton(TRUE);
}
}
// TODO: Remove this if you don't want tool tips
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY);
UpdateTimer = SetTimer(1, 1000, 0);
return 0;
}
void CMainFrame::InitializeTrayIcon()
{
memset(&m_tnd, 0, sizeof(m_tnd));
m_bEnabled = FALSE;
m_bHidden = FALSE;
m_hSavedIcon = NULL;
m_DefaultMenuItemID = 0;
m_DefaultMenuItemByPos = TRUE;
}
BOOL CMainFrame::CreateTrayIcon(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip,
HICON icon, UINT uID)
{
// this is only for Windows 95 (or higher)
VERIFY(m_bEnabled = ( GetVersion() & 0xff ) >= 4);
if (!m_bEnabled) return FALSE;
// Make sure Notification window is valid (not needed - CJM)
// VERIFY(m_bEnabled = (pParent && ::IsWindow(pParent->GetSafeHwnd())));
// if (!m_bEnabled) return FALSE;
// Make sure we avoid conflict with other messages
ASSERT(uCallbackMessage >= WM_USER);
// Tray only supports tooltip text up to 64 characters
ASSERT(_tcslen(szToolTip) <= 64);
// Create an invisible window
m_wndTrayIcon.CreateEx(0, AfxRegisterWndClass(0), _T(""), WS_POPUP, 0,0,10,10, NULL, 0);
// load up the NOTIFYICONDATA structure
m_tnd.cbSize = sizeof(NOTIFYICONDATA);
m_tnd.hWnd = pParent->GetSafeHwnd()? pParent->GetSafeHwnd() : m_wndTrayIcon.GetSafeHwnd();
m_tnd.uID = uID;
m_tnd.hIcon = icon;
m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
m_tnd.uCallbackMessage = uCallbackMessage;
_tcscpy(m_tnd.szTip, szToolTip);
// Set the tray icon
VERIFY(m_bEnabled = Shell_NotifyIcon(NIM_ADD, &m_tnd));
return m_bEnabled;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CMDIFrameWnd::PreCreateWindow(cs)) return FALSE;
if (!m_bOwnerCreated) // "dialog-is-created" flag
{
// m_MainFrameOwner - CDialog object mapped to the resource dialog template
m_bOwnerCreated = m_MainFrameOwner.Create(IDD_OWNERFRAME);
if (m_bOwnerCreated) m_MainFrameOwner.ShowWindow(SW_HIDE);
};
// set the dialog as a parent of CMainFrame window
if (m_bOwnerCreated)
{
cs.hwndParent = m_MainFrameOwner.GetSafeHwnd();
}
return TRUE;
}
BOOL CMainFrame::ShowTaskBarButton(BOOL bVisible)
{
if (!m_bOwnerCreated) return FALSE;
// ShowWindow(SW_HIDE); // seems to cause various problems,
// ranging from flashing windows to the title bar disappearing
if (bVisible)
ModifyStyleEx(0, WS_EX_APPWINDOW);
else
ModifyStyleEx(WS_EX_APPWINDOW, 0);
// ShowWindow(SW_SHOW);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CMDIFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CMDIFrameWnd::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
CDialogBar* CMainFrame::GetDialogBar()
{
return &m_wndDlgBar;
}
void CMainFrame::OnTimer(UINT nIDEvent)
{
if(nIDEvent == UpdateTimer)
{
int decimal, sign;
float BytesIn = (float) Doc->GnuComm->BytesIn,
BytesOut = (float) Doc->GnuComm->BytesOut,
ByteLimit = (float) Doc->m_LimitTotal,
Kilo = 1024;
// call thread flow control OnTimer only once a second
Doc->GnuComm->OnTimer();
// Reset
Doc->GnuComm->BytesIn = 0;
Doc->GnuComm->BytesOut = 0;
// The the estimated speed for gnucleus
Doc->m_EstSpeed = GetEstSpeed(BytesIn * 8 / 1024);
// Receive status bar update
float Old_RecvSpeed = atof(m_wndStatusBar.GetPaneText(1));
// CString Speed = _fcvt( ((BytesIn / Kilo) + Old_RecvSpeed) / 2, 2, &decimal, &sign );
CString Speed = _fcvt( Doc->GnuComm->m_dwBytesPerSecIn / Kilo, 2, &decimal, &sign );
Speed.Insert(decimal, ".");
CString Title = "Receive rate: ";
Title += Speed;
Title += " KB/s";
m_wndStatusBar.SetPaneText(1, Title);
// Send status bar update
float Old_SendSpeed = atof(m_wndStatusBar.GetPaneText(2));
// Speed = _fcvt( ((BytesOut / Kilo) + Old_SendSpeed) / 2, 2, &decimal, &sign );
Speed = _fcvt( Doc->GnuComm->m_dwBytesPerSecOut / Kilo, 2, &decimal, &sign );
Speed.Insert(decimal, ".");
Title = "Send rate: ";
Title += Speed;
Title += " KB/s";
m_wndStatusBar.SetPaneText(2, Title);
/*
// Drop if limit hit
float AverageSpeed = (((BytesOut + BytesIn) / Kilo) + (Old_RecvSpeed + Old_SendSpeed)) / 2;
if(ByteLimit != 0)
if(ByteLimit < AverageSpeed)
if(AverageSpeed - ByteLimit > 1)
Strike++;
else
Strike = 0;
*/
// If limit is hit 3 times in a row, drop the connection
if(Strike > 10)
{
Strike = 0;
Doc->m_ConnectNum--;
if( Doc->m_ConnectNum == 0)
AfxMessageBox("Not enough bandwidth to support Gnucleus.");
((CViewConnect * ) ((CGnucleusApp *) AfxGetApp())->ConnectFrame->GetActiveView())->RemoveFirstNode();
}
}
CMDIFrameWnd::OnTimer(nIDEvent);
}
DWORD CMainFrame::GetEstSpeed(DWORD CurrentSpeed)
{
if(CurrentSpeed <= Doc->m_EstSpeed)
return Doc->m_EstSpeed;
else
{
if(CurrentSpeed > 45000)
return 45000;
if(CurrentSpeed > 1500)
return 1500;
if(CurrentSpeed > 768)
return 768;
if(CurrentSpeed > 384)
return 384;
if(CurrentSpeed > 128)
return 128;
if(CurrentSpeed > 56)
return 56;
if(CurrentSpeed > 53)
return 53;
if(CurrentSpeed > 29)
return 29;
if(CurrentSpeed > 14)
return 14;
}
return 0;
}
BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
{
// Entering return in they keyword box submits a search
if(wParam == 1 && lParam == 0)
{
((CGnucleusApp *) AfxGetApp())->OnButtonSearch();
}
return CMDIFrameWnd::OnCommand(wParam, lParam);
}
void CMainFrame::OnOpenFromTray()
{
this->ShowWindow(SW_RESTORE);
HideIcon();
ShowTaskBarButton(TRUE);
}
void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
CMDIFrameWnd::OnShowWindow(bShow, nStatus);
// I don't know what the following code needs to be here for,
// but it makes a massive headache on Win 9x (stack overflow).
/*
if (bShow)
{
HideIcon();
ShowTaskBarButton(TRUE);
}
*/
}
/////////////////////////////////////////////////////////////////////////////
// Tray Icon manipulation
void CMainFrame::MoveToRight()
{
HideIcon();
ShowIcon();
}
void CMainFrame::RemoveIcon()
{
if (!m_bEnabled) return;
m_tnd.uFlags = 0;
Shell_NotifyIcon(NIM_DELETE, &m_tnd);
m_bEnabled = FALSE;
}
void CMainFrame::HideIcon()
{
if (m_bEnabled && !m_bHidden) {
m_tnd.uFlags = NIF_ICON;
Shell_NotifyIcon (NIM_DELETE, &m_tnd);
m_bHidden = TRUE;
}
}
void CMainFrame::ShowIcon()
{
if (m_bEnabled && m_bHidden) {
m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
Shell_NotifyIcon(NIM_ADD, &m_tnd);
m_bHidden = FALSE;
}
}
BOOL CMainFrame::SetIcon(HICON hIcon)
{
if (!m_bEnabled) return FALSE;
m_tnd.uFlags = NIF_ICON;
m_tnd.hIcon = hIcon;
return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
}
BOOL CMainFrame::SetIcon(LPCTSTR lpszIconName)
{
HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);
return SetIcon(hIcon);
}
BOOL CMainFrame::SetIcon(UINT nIDResource)
{
HICON hIcon = AfxGetApp()->LoadIcon(nIDResource);
return SetIcon(hIcon);
}
BOOL CMainFrame::SetStandardIcon(LPCTSTR lpIconName)
{
HICON hIcon = LoadIcon(NULL, lpIconName);
return SetIcon(hIcon);
}
BOOL CMainFrame::SetStandardIcon(UINT nIDResource)
{
HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(nIDResource));
return SetIcon(hIcon);
}
HICON CMainFrame::GetIcon() const
{
return (m_bEnabled)? m_tnd.hIcon : NULL;
}
/////////////////////////////////////////////////////////////////////////////
// Tray Icon tooltip text manipulation
BOOL CMainFrame::SetTooltipText(LPCTSTR pszTip)
{
if (!m_bEnabled) return FALSE;
m_tnd.uFlags = NIF_TIP;
_tcscpy(m_tnd.szTip, pszTip);
return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
}
BOOL CMainFrame::SetTooltipText(UINT nID)
{
CString strText;
VERIFY(strText.LoadString(nID));
return SetTooltipText(strText);
}
CString CMainFrame::GetTooltipText() const
{
CString strText;
if (m_bEnabled)
strText = m_tnd.szTip;
return strText;
}
/////////////////////////////////////////////////////////////////////////////
// Tray Icon notification window stuff
BOOL CMainFrame::SetNotificationWnd(CWnd* pWnd)
{
if (!m_bEnabled) return FALSE;
// Make sure Notification window is valid
ASSERT(pWnd && ::IsWindow(pWnd->GetSafeHwnd()));
m_tnd.hWnd = pWnd->GetSafeHwnd();
m_tnd.uFlags = 0;
return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
}
CWnd* CMainFrame::GetNotificationWnd() const
{
return CWnd::FromHandle(m_tnd.hWnd);
}
/////////////////////////////////////////////////////////////////////////////
// Tray Icon menu manipulation
BOOL CMainFrame::SetMenuDefaultItem(UINT uItem, BOOL bByPos)
{
if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos == bByPos))
return TRUE;
m_DefaultMenuItemID = uItem;
m_DefaultMenuItemByPos = bByPos;
CMenu menu, *pSubMenu;
if (!menu.LoadMenu(m_tnd.uID)) return FALSE;
if (!(pSubMenu = menu.GetSubMenu(0))) return FALSE;
::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
return TRUE;
}
void CMainFrame::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)
{
uItem = m_DefaultMenuItemID;
bByPos = m_DefaultMenuItemByPos;
}
LRESULT CMainFrame::OnTrayNotification(UINT wParam, LONG lParam)
{
//Return quickly if its not for this tray icon
if (wParam != m_tnd.uID)
return 0L;
CMenu menu, *pSubMenu;
CWnd* pTarget = AfxGetMainWnd();
// Clicking with right button brings up a context menu
if (LOWORD(lParam) == WM_RBUTTONUP)
{
if (!menu.LoadMenu(m_tnd.uID)) return 0;
if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
// Make chosen menu item the default (bold font)
::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
// Display and track the popup menu
CPoint pos;
GetCursorPos(&pos);
pTarget->SetForegroundWindow();
::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0,
pTarget->GetSafeHwnd(), NULL);
// BUGFIX: See "PRB: Menus for Notification Icons Don't Work Correctly"
pTarget->PostMessage(WM_NULL, 0, 0);
menu.DestroyMenu();
}
else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
{
// double click received, the default action is to execute default menu item
pTarget->SetForegroundWindow();
UINT uItem;
if (m_DefaultMenuItemByPos)
{
if (!menu.LoadMenu(m_tnd.uID)) return 0;
if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID);
}
else
uItem = m_DefaultMenuItemID;
pTarget->SendMessage(WM_COMMAND, uItem, 0);
menu.DestroyMenu();
}
return 1;
}
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == m_tnd.uCallbackMessage)
return OnTrayNotification(wParam, lParam);
return CWnd::WindowProc(message, wParam, lParam);
}
BOOL CMainFrame::OnNcActivate(BOOL bActive)
{
// Add iconize button to caption
DrawButtons( GetSafeHwnd() );
return CMDIFrameWnd::OnNcActivate(bActive);
}
void CMainFrame::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
HDC hDc ;
RECT rPos ;
RECT rWin ;
// Redraw caption buttons
if ( ( hDc = ::GetWindowDC( GetSafeHwnd() ) ) != NULL )
{
// Convert mouse postion relative to caption rectangle
GetWindowRect(&rWin);
// Calculate rectangle position of iconize button
CalcCaptionRect( GetSafeHwnd(), rPos );
rPos.top += 2;
rPos.bottom -= 2;
rPos.right -= ( ( GetSystemMetrics( SM_CXSIZE ) * 3 ) );
rPos.left = rPos.right - ( GetSystemMetrics( SM_CXSIZE ) - 2 );
point.x = point.x - rWin.left;
point.y = point.y - rWin.top;
// Check if mouse position is in rectangle
if ( PtInRect( &rPos, point) )
{
SendMessage( WM_SYSCOMMAND, SC_MINIMIZE, 0 );
ShowWindow( SW_HIDE );
ShowIcon();
ShowTaskBarButton(FALSE);
}
else
CMDIFrameWnd::OnNcLButtonUp(nHitTest, point);
DrawFrameControl( hDc, &rPos, DFC_BUTTON, DFCS_BUTTONPUSH );
DrawIconize( hDc, rPos.left, rPos.top, 0 );
m_LBtnDown = FALSE;
DeleteObject( hDc );
}
}
void CMainFrame::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
HDC hDc ;
RECT rPos ;
RECT rWin ;
// Redraw caption buttons
if ( ( hDc = ::GetWindowDC( GetSafeHwnd()) ) != NULL )
{
// Convert mouse postion relative to caption rectangle
::GetWindowRect( GetSafeHwnd(), &rWin );
// Calculate rectangle position of iconize button
CalcCaptionRect( GetSafeHwnd(), rPos );
rPos.top += 2;
rPos.bottom -= 2;
rPos.right -= ( ( GetSystemMetrics( SM_CXSIZE ) * 3 ) );
rPos.left = rPos.right - ( GetSystemMetrics( SM_CXSIZE ) - 2 );
point.x = point.x - rWin.left;
point.y = point.y - rWin.top;
// Check if mouse position is in rectangle
if ( PtInRect( &rPos, point) )
{
m_LBtnDown = TRUE;
DrawFrameControl( hDc, &rPos, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED );
DrawIconize( hDc, rPos.left, rPos.top, 1 );
}
else
CMDIFrameWnd::OnNcLButtonDown(nHitTest, point) ;
DeleteObject( hDc );
}
}
void CMainFrame::OnNcMouseMove(UINT nHitTest, CPoint point)
{
HDC hDc ;
RECT rPos ;
RECT rWin ;
// Redraw caption buttons
if ( ( hDc = ::GetWindowDC( GetSafeHwnd() ) ) != NULL )
{
// Convert mouse postion relative to caption rectangle
::GetWindowRect( GetSafeHwnd(), &rWin );
// Calculate rectangle position of iconize button
CalcCaptionRect( GetSafeHwnd(), rPos );
rPos.top += 2;
rPos.bottom -= 2;
rPos.right -= ( ( GetSystemMetrics( SM_CXSIZE ) * 3 ) );
rPos.left = rPos.right - ( GetSystemMetrics( SM_CXSIZE ) - 2 );
point.x = point.x - rWin.left;
point.y = point.y - rWin.top;
// Check if mouse position is in rectangle
if ( PtInRect( &rPos, point) )
{
DrawFrameControl( hDc, &rPos, DFC_BUTTON, ( m_LBtnDown ) ? DFCS_BUTTONPUSH | DFCS_PUSHED : DFCS_BUTTONPUSH );
DrawIconize( hDc, rPos.left, rPos.top, ( m_LBtnDown ) ? 1 : 0 );
}
else
{
m_LBtnDown = FALSE;
DrawFrameControl( hDc, &rPos, DFC_BUTTON, DFCS_BUTTONPUSH );
DrawIconize( hDc, rPos.left, rPos.top, 0 );
CMDIFrameWnd::OnNcMouseMove(nHitTest, point) ;
}
DeleteObject( hDc );
}
}
void CMainFrame::OnNcPaint()
{
CMDIFrameWnd::OnNcPaint();
// Add iconize button to caption
DrawButtons( GetSafeHwnd() );
}
void CMainFrame::CalcCaptionRect( HWND hWnd, RECT& Rect )
{
DWORD dStyle ;
SIZE sFrame ;
int Icon ;
// Get frame size of window
dStyle = GetWindowLong( hWnd, GWL_STYLE );
sFrame.cx = GetSystemMetrics( ( dStyle & WS_THICKFRAME ) ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME );
sFrame.cy = GetSystemMetrics( ( dStyle & WS_THICKFRAME ) ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME );
// Get width of icon/button in caption
Icon = GetSystemMetrics( SM_CXSIZE );
// Calculate rectangle dimensions
::GetWindowRect( hWnd, &Rect );
Rect.bottom -= Rect.top;
Rect.right -= Rect.left;
Rect.top = 0;
Rect.left = 0;
Rect.left += sFrame.cx;
Rect.right -= sFrame.cx;
Rect.top += sFrame.cy;
Rect.bottom = Rect.top + GetSystemMetrics( SM_CYCAPTION )
- GetSystemMetrics( SM_CYBORDER );
}
void CMainFrame::DrawIconize( HDC hDc, int x, int y, int off )
{
//
// TODO:
// This should be done flikker free by means
// of a memory DC
//
HPEN Pen, oldPen;
HBRUSH Brush, oldBrush;
int cxBtn = GetSystemMetrics( SM_CXSIZE ) - 5;
int cyBtn = GetSystemMetrics( SM_CYSIZE ) - 5;
Pen = CreatePen( PS_SOLID, 1, RGB( 0, 0, 0 ) );
oldPen = (HPEN) SelectObject( hDc, Pen );
Brush = CreateSolidBrush( RGB(0,0,0) );
oldBrush = (HBRUSH) SelectObject(hDc, Brush);
// Use a filled circle in the bottom right corner to signify minimize to icon.
Ellipse(hDc, x + 1 + cxBtn*1/2 + off, y + 1 + cyBtn*1/2,
x + 1 + cxBtn*5/6, y + 1 + cyBtn*3/4);
SelectObject( hDc, oldPen );
DeleteObject( Pen );
SelectObject( hDc, oldBrush );
DeleteObject( Brush );
}
void CMainFrame::DrawButtons( HWND hWnd )
{
HDC hDc ;
RECT rCap ;
DWORD dStyle ;
DWORD dExStyle ;
int cxBtn ;
int cyBtn ;
RECT rPos ;
// Get window device context
if ( ( hDc = ::GetWindowDC( hWnd ) ) != NULL )
{
// Get caption coordinates
CalcCaptionRect( hWnd, rCap );
// Get window style
dStyle = GetWindowLong( hWnd, GWL_STYLE );
dExStyle = GetWindowLong( hWnd, GWL_EXSTYLE );
// Check if we have a caption
if ( ( dStyle & WS_CAPTION ) == WS_CAPTION )
{
// Get button dimensions
cxBtn = GetSystemMetrics( SM_CXSIZE );
cyBtn = GetSystemMetrics( SM_CYSIZE );
// Calc position and draw close button
rPos.top = rCap.top + 2;
rPos.bottom = rCap.bottom - 2;
rPos.right = rCap.right - 2;
rPos.left = rCap.right - 2 - ( cxBtn - 2);
DrawFrameControl( hDc, &rPos, DFC_CAPTION, DFCS_CAPTIONCLOSE );
// Calc position and draw maximize<->restore/help button
if ( ( dStyle & WS_MAXIMIZEBOX ) == WS_MAXIMIZEBOX )
{
rPos.right -= cxBtn;
rPos.left -= cxBtn;
DrawFrameControl( hDc, &rPos, DFC_CAPTION, ::IsZoomed( hWnd ) ? DFCS_CAPTIONRESTORE
: DFCS_CAPTIONMAX );
}
else if ( ( dExStyle & WS_EX_CONTEXTHELP ) == WS_EX_CONTEXTHELP )
{
rPos.right -= cxBtn;
rPos.left -= cxBtn;
DrawFrameControl( hDc, &rPos, DFC_CAPTION, DFCS_CAPTIONHELP );
}
// Calc position and draw minimize and iconize button
if ( ( dStyle & WS_MINIMIZEBOX ) == WS_MINIMIZEBOX )
{
// Minimize button
rPos.right -= ( cxBtn - 2 );
rPos.left -= ( cxBtn - 2 );
DrawFrameControl( hDc, &rPos, DFC_CAPTION, DFCS_CAPTIONMIN );
// Iconize button
rPos.right -= ( cxBtn - 2 ) + 2;
rPos.left -= ( cxBtn - 2 ) + 2;
DrawFrameControl( hDc, &rPos, DFC_BUTTON, DFCS_BUTTONPUSH );
// Draw a btnface
DrawIconize( hDc, rPos.left, rPos.top, 0 );
}
}
// Release device context
::ReleaseDC( hWnd, hDc );
}
}
void CMainFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
// Add iconize button to caption
DrawButtons( GetSafeHwnd() );
}